//FIFO MODEL
//DHEERAJ KUMAR BISWAS

//`include "apbMaster.v"

module fifo(clk,
			resetn,
			full,
			empty,
			writeEnable,
			readEnable,
			dataWrite,
			dataRead);

    //parameters
	parameter DATA_WIDTH = 32;										
	parameter ADDR_WIDTH = 10;
	parameter WR1_RD0	 = 1;
	parameter SLV_SEL 	 = 2;
	parameter DEPTH 	 = 10;
	parameter CMD_LENGTH = DATA_WIDTH + ADDR_WIDTH + WR1_RD0 + SLV_SEL;
    //fifo signal Declarations
	output 							full;
	output 							empty;
	output reg 	[CMD_LENGTH-1:0]	dataRead;

    //output reg 	[CMD_LENGTH-1: 0]	cmd;
	input 							clk;
	input							resetn;
	input							writeEnable;
	input							readEnable;
	input		[CMD_LENGTH-1:0]	dataWrite;

    //internal signals declarations
	reg 		[CMD_LENGTH-1:0] 	fifomem [DEPTH-1:0];
	reg 		[3:0]			 	wrptr;
	reg 		[3:0] 			 	rdptr;
	integer 					 	i;

  assign full = (((rdptr - 1) == wrptr) || (((DEPTH - 1) == wrptr) && rdptr == 0))? 1: 0;
	assign empty = (rdptr == wrptr)? 1: 0;

	always @(posedge clk or negedge resetn) begin
		if(!resetn) begin
			wrptr <= 0;
			rdptr <= 0;
          dataRead <= {CMD_LENGTH{1'bz}};
			for(i=0; i<DEPTH; i=i+1)
				fifomem[i] <= {CMD_LENGTH{1'b0}};		
		end			
		else if(writeEnable || readEnable)begin
			if(writeEnable)begin
				if(!full)begin
					fifomem[wrptr] <= dataWrite;
					wrptr = wrptr + 1;
				end
			end
			if(readEnable)begin
				if(!empty)begin
					dataRead <= fifomem[rdptr];
					rdptr = rdptr + 1;
				end
				else begin
					//if readEanble is not active then tristate dataRead is available
					dataRead <= {CMD_LENGTH{1'bz}};
				end
			end
		end

		//pointer overflow control for depth < 2**n 
		//if pointers are declared as [3:0] then overflow is not required to be control
		if(rdptr >= DEPTH) begin
			rdptr <= 0;
		end
		else if(wrptr >= DEPTH) begin
			wrptr <= 0;
		end
	end
endmodule
